package com.zhj.agent.interceptor.httpservlet;

import com.zhj.agent.common.ConstName;
import com.zhj.agent.core.RuntimeContextManager;
import com.zhj.agent.support.InstanceMethodsAroundInterceptor;

import java.lang.reflect.Method;
import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import lombok.extern.slf4j.Slf4j;


@Slf4j
public class HttpServletInterceptor implements InstanceMethodsAroundInterceptor {

    /**
     * Before method
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @throws Throwable throwable
     * @since 1.0.0
     */
    @Override
    public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable {
        HttpServletRequest httpRequest = (HttpServletRequest) allArguments[0];
        Enumeration<String> headers = httpRequest.getHeaders(ConstName.HEAD_KEY);
        //将请求头的数据读取出来后清除掉头部数据
        if (headers.hasMoreElements()) {
            String nextElement = headers.nextElement();
            RuntimeContextManager.CarrierItem carrierItem
                = RuntimeContextManager.CarrierItem.item(nextElement, nextElement);
            RuntimeContextManager.add(carrierItem);
        }
        RuntimeContextManager.CarrierItem next = RuntimeContextManager.CarrierItem.item(System.getProperty(ConstName.CONFIG_APP_NAME),
                                                                                        System.getProperty(ConstName.CONFIG_APP_NAME));
        RuntimeContextManager.add(next);
        httpRequest.removeAttribute(ConstName.HEAD_KEY);
    }

    /**
     * After method
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @param result         result
     * @return the object
     * @throws Throwable throwable
     * @since 1.0.0
     */
    @Override
    public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable {
        HttpServletResponse httpServletResponse = (HttpServletResponse) allArguments[1];
        RuntimeContextManager.addResponseHeaders(httpServletResponse);
        RuntimeContextManager.printTraceLog();
        RuntimeContextManager.remove();
        return result;
    }

    /**
     * Handle method exception
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @param t              t
     * @since 1.0.0
     */
    @Override
    public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
        RuntimeContextManager.printTraceLog();
        RuntimeContextManager.remove();
    }

}
